home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / MacSource / stdfolder.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-14  |  11.9 KB  |  345 lines  |  [TEXT/CWIE]

  1. /*==============================================================================
  2. Project:    POV
  3.  
  4. Version:    3
  5.  
  6. File:        StdFolder.c
  7.  
  8. Description:
  9.     Routines to Prompt user to choose a folder (not a file) via almost-StdFile dialog.
  10. ------------------------------------------------------------------------------
  11. Author:
  12.     Eduard [esp] Schwan
  13. ------------------------------------------------------------------------------
  14.     from Persistence of Vision(tm) Ray Tracer
  15.     Copyright 1996 Persistence of Vision Team
  16. ------------------------------------------------------------------------------
  17.     NOTICE: This source code file is provided so that users may experiment
  18.     with enhancements to POV-Ray and to port the software to platforms other 
  19.     than those supported by the POV-Ray Team.  There are strict rules under
  20.     which you are permitted to use this file.  The rules are in the file
  21.     named POVLEGAL.DOC which should be distributed with this file. If 
  22.     POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  23.     Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  24.     Forum.  The latest version of POV-Ray may be found there as well.
  25.  
  26.     This program is based on the popular DKB raytracer version 2.12.
  27.     DKBTrace was originally written by David K. Buck.
  28.     DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  29. ------------------------------------------------------------------------------
  30. Change History:
  31.     950401    [esp]    Stole idea and converted some code from DTS Pascal sample, with lots of changes.
  32. ==============================================================================*/
  33.  
  34. #define STDFOLDER_C
  35.  
  36. #include "stdfolder.h"
  37.  
  38. #include <string.h>        // strcmp
  39. #include <memory.h>        // BlockMove
  40. #include <textutils.h>    // TruncString
  41. #include <LowMem.h>        // LM...
  42.  
  43.  
  44. #define    kFolderBit        4    // bit set in ioFlAttrib for a directory
  45.  
  46. #define    kGetDirBTN        10    // dlog item, Select directory button
  47. #define    kDirNameST        11    // dlog item, Select directory name static text
  48. #define    kPromptST        12    // dlog item, Prompt static text
  49.  
  50.  
  51. static Boolean        gDirSelectionFlag;
  52. static Str63        gPrevSelectedName;
  53. static Str255        gThePrompt;
  54.  
  55.  
  56. // ---------------------------------------------------------------------
  57. // Set default SF Getfile dialog initial directory
  58. void SF_SetSFCurrent(FSSpecPtr pTheFSFilePtr)
  59. {
  60.     OSErr        anError = noErr;
  61.  
  62.     // Standard File wants the dirID and the negated vRefnum..
  63.     // so give it to 'em that way
  64.     LMSetCurDirStore(pTheFSFilePtr->parID);
  65.     LMSetSFSaveDisk(-(pTheFSFilePtr->vRefNum));
  66.  
  67. } // SF_SetSFCurrent
  68.  
  69.  
  70. // ---------------------------------------------------------------------
  71. // Get default SF Getfile dialog initial volume
  72. short SF_GetSFCurVol(void)
  73. {
  74.     return -LMGetSFSaveDisk();
  75. } // SF_GetSFCurVol
  76.  
  77.  
  78. // ---------------------------------------------------------------------
  79. // Get default SF Getfile dialog initial directory
  80. long SF_GetSFCurDir(void)
  81. {
  82.     return LMGetCurDirStore();
  83. } // SF_GetSFCurDir
  84.  
  85.  
  86. /*
  87. ---------------------------------------------------------------------------------
  88.     The file filter function used to select directories is quite simple; it
  89.     ensures that only directories, not files, are listed in the dialog box
  90.     displayed by CustomGetFile.  The function MyCustomFileFilter simply
  91.     inspects the appropriate bit in the file attributes (ioFlAttrib) field of
  92.     the catalog information parameter block passed to it. If the directory bit
  93.     is set, the file filter function returns false, indicating that the item
  94.     should appear in the list; otherwise, the file filter function returns
  95.     true to exclude the item from the list. Because a volume is identified via
  96.     its root directory, volumes also appear in the list of items in the dialog
  97.     box. 
  98. */
  99. static pascal Boolean SFCustomFileFilter(CInfoPBPtr pb, void *myDataPtr)
  100. {    /*list directories only*/
  101. #pragma unused(myDataPtr)
  102.     short    fileAttributes;
  103.  
  104.     fileAttributes = (pb->hFileInfo.ioFlAttrib >> kFolderBit) & 0x01;
  105.  
  106.     return (fileAttributes == 0);
  107. } // SFCustomFileFilter
  108.  
  109.  
  110. /*
  111. ---------------------------------------------------------------------------------
  112.     The title of the Select button should identify which directory is
  113.     available for selection.  The ShowFolderItem procedure is passed a handle
  114.     to the button whose title is to be changed, the name of the directory
  115.     available for selection, && the button’s enclosing rectangle. The global
  116.     variable gPrevSelectedName holds the full directory name, before
  117.     truncation. 
  118. */
  119. static void ShowFolderItem(DialogPtr theDialog, Str255 folderName)
  120. {
  121.     short    result;            /*result of TruncString*/
  122.     short    width;            /*width available for name of directory*/
  123.     short    stItemType;        /*needed for GetDialogItem*/
  124.     Handle    stItemHdl;        /*needed for GetDialogItem*/
  125.     Rect    stItemRect;        /*needed for GetDialogItem*/
  126.  
  127.     // find the custom static text in dialog
  128.     GetDialogItem(theDialog, kDirNameST, &stItemType, &stItemHdl, &stItemRect);
  129.  
  130.     // Pascal string copy
  131.     BlockMove(folderName, gPrevSelectedName, folderName[0]+1);
  132.  
  133.     // truncate string to fit into rect
  134.     width = stItemRect.right - stItemRect.left - 2;
  135.     result = TruncString(width, folderName, truncMiddle); /* Script Mgr call */
  136.  
  137.     // stuff folder name into display field
  138.     SetDialogItemText((Handle)stItemHdl, folderName);
  139.  
  140. } // ShowFolderItem
  141.  
  142.  
  143. static void ShowPrompt(DialogPtr theDialog)
  144. {
  145.     short    stItemType;        /*needed for GetDialogItem*/
  146.     Handle    stItemHdl;        /*needed for GetDialogItem*/
  147.     Rect    stItemRect;        /*needed for GetDialogItem*/
  148.  
  149.     // find the custom static text in dialog
  150.     GetDialogItem(theDialog, kPromptST, &stItemType, &stItemHdl, &stItemRect);
  151.  
  152.     // stuff folder name into display field
  153.     SetDialogItemText((Handle)stItemHdl, gThePrompt);
  154.  
  155. } // ShowPrompt
  156.  
  157.  
  158.  
  159. /*
  160. ---------------------------------------------------------------------------------
  161.     The dialog hook function calls the ShowFolderItem procedure to copy the
  162.     truncated title of the selected item into the Select button. This title
  163.     eliminates possible user confusion about which directory is available for
  164.     selection. If no item in the list is selected, the dialog hook function
  165.     uses the name of the directory shown in the pop-up menu as the title of
  166.     the Select button. A dialog hook function manages most of the process of
  167.     letting the user select a director.  The MyDlgHook dialog hook function
  168.     defined in Listing 3-18 calls the File Manager function PBGetCatInfo to
  169.     retrieve the name of the directory to be selected. When the dialog hook
  170.     function is first called (that is, when item is set to sfHookFirstCall),
  171.     MyDlgHook determines the current volume && directory by calling the
  172.     functions GetSFCurVol && GetSFCurDir. When MyDlgHook is called each
  173.     subsequent time, MyDlgHook calls PBGetCatInfo with the volume reference
  174.     number && directory ID of the previously opened directory. 
  175. */
  176. static pascal short SF_DlgHook(short itemHit, DialogPtr theDialog, void * myDataPtr)
  177.  
  178. {
  179.     short        returnItem;        /*what to return*/
  180.     Str63        myName;
  181.     CInfoPBRec    myPB;
  182.     StandardFileReply    *mySFRPtr;
  183.     OSErr        myErr;
  184.  
  185.     returnItem = itemHit;    /*default, except in special cases below*/
  186.  
  187.     if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon)
  188.     {    // this function is only for main dialog box
  189.  
  190.         if (itemHit == sfHookFirstCall)
  191.         {
  192.                 /* Determine current folder name */
  193.                 myPB.hFileInfo.ioCompletion    = NULL;
  194.                 myPB.hFileInfo.ioNamePtr    = myName;
  195.                 myPB.hFileInfo.ioVRefNum    = SF_GetSFCurVol();
  196.                 myPB.hFileInfo.ioFDirIndex    = -1;
  197.                 myPB.hFileInfo.ioDirID        = SF_GetSFCurDir();
  198.                 myErr = PBGetCatInfoSync(&myPB);
  199.                 /* set title of Select button first time in */
  200.                 ShowFolderItem(theDialog, myName);
  201.                 ShowPrompt(theDialog);
  202.         }
  203.         else if (itemHit != sfHookLastCall)
  204.         {
  205.             /* Get mySFRPtr from 3rd parameter to hook function. */
  206.             mySFRPtr = (StandardFileReply*)myDataPtr;
  207.             // Track name of folder that can be selected.
  208.             if ((mySFRPtr->sfIsFolder) || (mySFRPtr->sfIsVolume))
  209.             {    // user selected an item in the SFList
  210.                 BlockMove(mySFRPtr->sfFile.name, myName, mySFRPtr->sfFile.name[0]+1);
  211.             }
  212.             else
  213.             {
  214.                 // get name of parent folder if no folder/volume selected
  215.                 myPB.hFileInfo.ioCompletion    = NULL;
  216.                 myPB.hFileInfo.ioNamePtr    = myName;
  217.                 myPB.hFileInfo.ioVRefNum    = mySFRPtr->sfFile.vRefNum;
  218.                 myPB.hFileInfo.ioFDirIndex    = -1;
  219.                 myPB.dirInfo.ioDrDirID        = mySFRPtr->sfFile.parID;
  220.                 myErr = PBGetCatInfoSync(&myPB);
  221.                 mySFRPtr->sfFile.parID = myPB.dirInfo.ioDrParID;
  222.  
  223.                 // fix up sfIsVolume/sfIsFolder depending on choice
  224.                 if (mySFRPtr->sfFile.parID == fsRtDirID)
  225.                     mySFRPtr->sfIsVolume = -1;    // in root directory
  226.                 else
  227.                     mySFRPtr->sfIsFolder = -1;    // down in directory or dir selected
  228.             }
  229.  
  230.             // Change directory name in button title if changed.
  231.             // Note the tricky Pascal string compare.
  232.             if (strncmp((char*)myName, (char*)gPrevSelectedName, myName[0]+1) != 0)
  233.             {
  234.                 ShowFolderItem(theDialog, myName);
  235.             }
  236.  
  237.             switch (itemHit)
  238.             {
  239.                 case kGetDirBTN:                    /* force return by faking a cancel */
  240.                     returnItem = sfItemCancelButton;
  241.                     break;
  242.                 case sfItemCancelButton:
  243.                     gDirSelectionFlag = false;        /* flag no directory was selected */                        
  244.                     break;
  245.             }
  246.         } // else not first call
  247.     } // if main dialog box
  248.  
  249.     return returnItem;
  250.  
  251. } // SF_DlgHook
  252.  
  253.  
  254.  
  255. /*
  256. ---------------------------------------------------------------------------------
  257.     The function PromptForFolder uses the file filter
  258.     function and the dialog hook functions defined above to manage the
  259.     directory selection dialog box. On exit, DoGetDirectory returns a standard
  260.     file reply record describing the selected directory. The DoGetDirectory
  261.     function initializes the two global variables gPrevSelectedName &&
  262.     gDirSelectionFlag. As you have seen, these two variables are used by the
  263.     custom dialog hook function. PromptForFolder  calls CustomGetFile to
  264.     display the directory selection dialog box & handle user selections.
  265.     When the user selects a directory or clicks the Cancel button, the dialog
  266.     hook function returns sfItemCancelButton & CustomGetFile exits. At that
  267.     point, the reply record contains information about the last item selected
  268.     in the list of available items. 
  269. */
  270.  
  271. Boolean SF_PromptForFolder(Point sfPoint, StringPtr aPrompt, StandardFileReply * sfrPtr)
  272. {
  273.     short                myNumTypes;
  274.     SFTypeList            myTypes;        /*types of files to display*/    
  275.     FileFilterYDUPP        myFileFilterUPP;
  276.     DlgHookYDUPP        myDlgHookUPP;
  277.  
  278.     gPrevSelectedName[0]    = '\0';        /*initialize name of previous selection*/
  279.     gDirSelectionFlag        = true;        /*initialize directory selection flag*/
  280.     myNumTypes                = -1;        /*allows invisible folders to show up*/
  281.  
  282.     myFileFilterUPP = NewFileFilterYDProc(SFCustomFileFilter);
  283.     myDlgHookUPP = NewDlgHookYDProc(SF_DlgHook);
  284.  
  285.     if (aPrompt)
  286.         BlockMove(aPrompt, gThePrompt, aPrompt[0]+1); // save the prompt
  287.     else
  288.         gThePrompt[0] = 0;
  289.  
  290.     CustomGetFile(    myFileFilterUPP,
  291.                     myNumTypes,
  292.                     myTypes,
  293.                     sfrPtr,
  294.                     rSF_FolderPromptDLOG,
  295.                     sfPoint,
  296.                     myDlgHookUPP,
  297.                     (ModalFilterYDUPP)NULL, 
  298.                     /*(ActivationOrderListPtr)*/NULL,
  299.                     (ActivateYDUPP)NULL,
  300.                     sfrPtr);
  301.  
  302.     DisposeRoutineDescriptor(myFileFilterUPP);
  303.     DisposeRoutineDescriptor(myDlgHookUPP);
  304.  
  305.     /*Get the name of the directory.*/
  306.     if (gDirSelectionFlag)
  307.     {
  308.         // Use saved name...
  309.         BlockMove(gPrevSelectedName, sfrPtr->sfFile.name, gPrevSelectedName[0]+1);
  310.         if (sfrPtr->sfIsVolume)
  311.         {
  312.             sfrPtr->sfFile.parID = fsRtDirID; // sometimes it's not! :-)
  313.         }
  314.     }
  315.  
  316.     /* did they choose something? */
  317.     sfrPtr->sfGood = gDirSelectionFlag;
  318.  
  319.     gDirSelectionFlag = false;
  320.  
  321.     return sfrPtr->sfGood;
  322.  
  323. } // SF_PromptForFolder
  324.  
  325.  
  326.  
  327. // ---------------------------------------------------------------------------------
  328. // If what you really wanted from SF_PromptForFolder was the folder's DirID,
  329. // and not its parent, pass the FSSpec in here and you'll get the next dirID down.
  330. long SF_GetFSSubDirID(FSSpecPtr theFSDir)
  331. {
  332.     OSErr        anError;
  333.     CInfoPBRec    myPB;
  334.  
  335.     // get name of parent folder if no folder/volume selected
  336.     myPB.hFileInfo.ioCompletion    = NULL;
  337.     myPB.hFileInfo.ioNamePtr    = theFSDir->name;
  338.     myPB.hFileInfo.ioVRefNum    = theFSDir->vRefNum;
  339.     myPB.hFileInfo.ioFDirIndex    = 0; // use ioNamePtr (-1 = ignore)
  340.     myPB.dirInfo.ioDrDirID        = theFSDir->parID;
  341.     anError = PBGetCatInfoSync(&myPB);
  342.     return myPB.dirInfo.ioDrDirID;
  343. } // SF_GetFSSubDirID
  344.  
  345.